home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Libraries / grayimage / image.h < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-30  |  17.3 KB  |  324 lines  |  [TEXT/R*ch]

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /*
  3.  ************************************************************************
  4.  *
  5.  *               Grayscale Image
  6.  *
  7.  *   The image is represented as a Pixmap, i.e. a matrix of pixels
  8.  *    each of them specifies the gray level at a particular point
  9.  *
  10.  *    The header file defines arithmetical and all other operations
  11.  *          permitted on the grayscale image
  12.  *
  13.  * $Id: image.h,v 1.14 1994/03/24 20:40:21 oleg Exp oleg $
  14.  *
  15.  ************************************************************************
  16.  */
  17.  
  18. //#pragma once
  19. #ifndef _image_h
  20. #define _image_h
  21.  
  22. #pragma interface
  23.  
  24. #include "myenv.h"
  25. #include <std.h>
  26.  
  27. typedef unsigned short GRAY;        // Pixel type
  28. typedef signed short GRAY_SIGNED;    // Pixel type, signed
  29. const int GRAY_MAXBIT = 8*sizeof(GRAY);    // Max no of bits per pixel
  30. const int GRAY_MAXVAL = ((1<<GRAY_MAXBIT)-1);
  31.  
  32.  
  33. class Rectangle;
  34. class rowcol;
  35. class Extrema;
  36. class IMAGE_to_PASS;
  37. class EndianIO;
  38.  
  39. typedef int USER_F(int);        // User function that can be applied
  40.                     // to the image
  41.  
  42. class IMAGE
  43. {
  44.   friend class Rectangle;
  45.   friend class Extrema;
  46.   
  47. private:            // Private part
  48.   int valid_code;            // Validation code
  49.   enum { IMAGE_val_code = 577767 };    // Image validation code
  50.   int ncols;                // Image width in pixels
  51.   int nrows;                // Image height in pixels
  52.   int npixels;                // Total no of pixels in the image
  53.   char * name;                // Image name
  54.   int bits_per_pixel;            // Image depth
  55.   GRAY ** scanrows;            // scanrows[i] = &pixels[i,0]
  56.   GRAY * pixels;            // pixels[i,j] is the
  57.                       // pixel value at point (i,j)
  58.                     // Pixels are ordered in rows
  59.  
  60.   void allocate(const int nrows, const int ncols, const int depth);
  61.  
  62.   void _expand(const IMAGE& prototype);    // Expand the prototype twice
  63.   void _shrink(const IMAGE& prototype);    // Shrink the prototype twice
  64.  
  65.                     // The following functions create an
  66.                     // image from a particular file
  67.                     // format. They call allocate()
  68.                     // to allocate the image data and
  69.                     // then read the data. The functions
  70.                     // are private to an IMAGE(file_name)
  71.                     // constructor and should be used
  72.                     // only by it
  73.   void read_xwd(EndianIO& file, const char verbose); // read an X Window dump
  74.   void read_pgm(EndianIO& file, const char verbose);// read a Portable GrayMap
  75.   void read_tiff(EndianIO& file, const char verbose);    // read TIFF
  76.  
  77. public:            // Public interface
  78.   
  79.                 // Constructors and destructors
  80.                       // Make a blank image
  81.   IMAGE(const int nrows, const int ncols, const int depth);
  82.   IMAGE(const IMAGE &image);        // Make a new blank image like 
  83.                     // Read an image from the file
  84.                     // Attempts to detect the file format
  85.   IMAGE(const char * file_name,const char print_header_info = 0);
  86.   IMAGE(const Rectangle& area);    // Make an image from a square area
  87.                     // of another image
  88.  
  89.                     // Construct an image applying a spec
  90.                     // operation to the prototype
  91.   enum IMAGE_CREATORS_1op { Expand, Shrink };
  92.   IMAGE(const IMAGE_CREATORS_1op op, const IMAGE& prototype);
  93.  
  94.   ~IMAGE();
  95.  
  96.   void is_valid() const
  97.   { assure(valid_code == IMAGE_val_code,"Invalid image"); }
  98.  
  99.                 // Status
  100.   int q_nrows() const            { return nrows; }
  101.   int q_ncols()    const            { return ncols; }
  102.   int q_depth()    const            { return bits_per_pixel; }
  103.   int q_npixels() const            { return npixels; }
  104.   const char * q_name() const          { return name; } 
  105.   void set_name(const char * new_name);    
  106.  
  107.                 // Individual pixel manipulations
  108.   GRAY& operator () (const int row, const int col) const;
  109.   GRAY& operator () (const rowcol pos) const;
  110.   void  sure_within(const rowcol pos) const;    // Make sure the pos
  111.                         // is within the image
  112.  
  113. // Row Column, Square operations
  114.  
  115.                 // Image-scalar operations
  116.  
  117.                 // Find out if the predicate
  118.                 // "(signed)pixel op val" is true for ALL
  119.                 // pixels of the image?
  120.   int operator ==  (const int val) const;    // ? (signed)pixels == val
  121.   int operator !=  (const int val) const;    // ? (signed)pixels != val
  122.   int operator <   (const int val) const;    // ? (signed)pixels <  val
  123.   int operator <=  (const int val) const;    // ? (signed)pixels <= val
  124.   int operator >   (const int val) const;    // ? (signed)pixels >  val
  125.   int operator >=  (const int val) const;    // ? (signed)pixels >= val
  126.  
  127.                 // Modify every element of the
  128.                 // image according to the operation
  129.   IMAGE& operator =   (const int val);        // Assignment to all the pixels
  130.   IMAGE& operator -=  (const int val);        // Diminish the brightness
  131.   IMAGE& operator +=  (const int val);        // Increase the brightness
  132.   IMAGE& operator *=  (const int val);
  133.   IMAGE& operator |=  (const int val);        // OR
  134.   IMAGE& operator &=  (const int val);        // , const int val);
  135.   friend void operator |=  (const Rectangle& sa, const int val);
  136.   friend void operator &=  (const Rectangle& sa, const int val);
  137.   friend void operator ^=  (const Rectangle& sa, const int val);
  138.   friend void operator <<= (const Rectangle& sa, const int val);
  139.   friend void operator >>= (const Rectangle& sa, const int val);
  140.  
  141.                     // Copy a rectangle a_rect into the
  142.                     // rectangular area of the image
  143.   Rectangle& operator = (const Rectangle& a_rect);
  144.  
  145.                       // Get a total sum of all the pixels
  146.   friend double sum_over(const Rectangle& sa);
  147. };
  148.  
  149. /*
  150.  *------------------------------------------------------------------------
  151.  *            Some service procedures
  152.  */
  153.  
  154. inline
  155. int log2(            // Find a binary logarithm of n
  156.     const int n )        // and check that n is a power of two
  157. {
  158.   register int i,k;
  159.  
  160.   assure(n > 0, "log2: the argument's got to be positive!");
  161.  
  162.   for(k=0,i=1; i < n; k++, i*=2)
  163.     ;
  164.   if( i != n )
  165.     _error("log2: the argument %d has got to be an exact power of two",n);
  166.  
  167.   return k;
  168. }
  169.  
  170. inline
  171. int exp2(const int k)            // Compute 2^k, k>=0
  172. {
  173.   assure(k >= 0, "exp2: the argument may not be negative!");
  174.   if( k > (signed)sizeof(int)*8-1 )
  175.     _error("exp2: the exponent %d is too big",k);
  176.  
  177.   return 1<<k;
  178. }
  179.  
  180. inline                    // return b * round( a/b )
  181. int round_to_even_multiple(const int a, const int b)
  182. {
  183.   assert( b > 0 );
  184.   register int rem = a % b;
  185.   if( 2*rem < b )
  186.     return a - rem;
  187.   else
  188.     return a + b - rem;
  189. }
  190.  
  191. /*
  192.  *------------------------------------------------------------------------
  193.  *            Inline Image Procedures
  194.  */
  195.  
  196. inline IMAGE::IMAGE(const int no_rows, const int no_cols, const int depth)
  197. {
  198.   allocate(no_rows,no_cols,depth);
  199. }
  200.  
  201.                     // Make a new image like the
  202. inline IMAGE::IMAGE(const IMAGE& old)    // old one
  203. {
  204.   allocate(old.nrows,old.ncols,old.bits_per_pixel);
  205. }
  206.  
  207. inline GRAY& IMAGE::operator () (const int row, const int col) const
  208. {
  209.   is_valid();
  210.   if( row >= nrows || row < 0 )
  211.     _error("Row index %d is out of image boundaries [0,%d]",row,nrows-1);
  212.   if( col >= ncols || col < 0 )
  213.     _error("Col index %d is out of image boundaries [0,%d]",col,ncols-1);
  214.   
  215.   return (scanrows[row])[col];
  216. }
  217.  
  218. inline GRAY& IMAGE::operator () (const rowcol pos) const
  219. {
  220.   return operator()(pos.row(),pos.col());
  221. }
  222.  
  223.                     // Make sure the pos is within the
  224.                     // image
  225. inline void  IMAGE::sure_within(const rowcol pos) const
  226. {
  227.   is_valid();
  228.   if( pos.row() >= nrows || pos.row() < 0 )
  229.     _error("Row index %d is out of image boundaries [0,%d]",pos.row(),nrows-1);
  230.   if( pos.col() >= ncols || pos.col() < 0 )
  231.     _error("Col index %d is out of image boundaries [0,%d]",pos.col(),ncols-1);
  232. }
  233.  
  234. inline IMAGE& IMAGE::clear(void)    // Clean the image
  235. {
  236.   is_valid();
  237.   memset(pixels,0,npixels*sizeof(GRAY));
  238.   return *this;
  239. }
  240.  
  241. inline IMAGE& IMAGE::invert(void)    // Invert the image
  242. {
  243.   is_valid();
  244.   return (*this ^= ((1<<bits_per_pixel)-1));
  245. }
  246.  
  247. inline void are_compatible(const IMAGE& im1, const IMAGE& im2)
  248. {
  249.   im1.is_valid();
  250.   im2.is_valid();
  251.   
  252.   if( im1.ncols != im2.ncols || im1.nrows != im2.nrows )
  253.     _error("The image %dx%d and the image %dx%d have different sizes",
  254.        im1.nrows,im1.ncols,im2.nrows,im2.ncols);
  255. }
  256.  
  257. inline int  operator == (const IMAGE& im1, const IMAGE& im2)
  258. {
  259.   return identical(im1,im2);
  260. }
  261.  
  262.  
  263.                 // Construct a square rectangle
  264. inline Rectangle::Rectangle
  265.     (IMAGE& im, const int sq_size, const rowcol pos)
  266.     : image(im), nrows(sq_size), ncols(sq_size)
  267. {
  268.   image.is_valid();
  269.  
  270.   if( pos.row() >= image.nrows || pos.row() < 0 ||
  271.       pos.row() + nrows > image.nrows ||
  272.       pos.col() >= image.ncols || pos.col() < 0 ||
  273.       pos.col() + ncols > image.ncols )
  274.     _error("Square area (left upper point [%d,%d], size %d)\n"
  275.        "is not within the image %dx%d",
  276.        pos.row(),pos.col(),sq_size,image.nrows,image.ncols);
  277.  
  278.   ptr  = &(image.scanrows[pos.row()][pos.col()]);
  279.   inc_to_nextrow = image.ncols - ncols;
  280. }
  281.  
  282.                 // Clip a square area from the image
  283. inline Rectangle IMAGE::square_of(const int size, const rowcol pos) const
  284. return c(*this, size, pos)
  285. {}
  286.  
  287.  
  288.                 // Make a rectangle with upper left corner
  289.                 // at uppleft position and lower right corner
  290.                 // at lowright position
  291. inline Rectangle::Rectangle
  292.     (IMAGE& im, const rowcol uppleft, const rowcol lowright)
  293.     : image(im), nrows(lowright.row()-uppleft.row()+1), 
  294.                  ncols(lowright.col()-uppleft.col()+1)
  295. {
  296.   image.is_valid();
  297.  
  298.   image.sure_within(uppleft);
  299.   image.sure_within(lowright);
  300.  
  301.   ptr  = &(image.scanrows[uppleft.row()][uppleft.col()]);
  302.   inc_to_nextrow = image.ncols - ncols;
  303. }
  304.  
  305.  
  306.                 // Clip a rectangular area from the image
  307. inline Rectangle IMAGE::rectangle(const rowcol uppleft,const rowcol lowright)
  308.                  const
  309. return c(*this, uppleft, lowright)
  310. {}
  311.  
  312.  
  313.                 // Treat the entire image as a rectangular area
  314. inline Rectangle::Rectangle (IMAGE& im)
  315.     : image(im), nrows(im.nrows), ncols(im.ncols)
  316. {
  317.   image.is_valid();
  318.  
  319.   ptr  = image.pixels;
  320.   inc_to_nextrow = 0;
  321. }
  322.  
  323. #endif
  324.